package com.chandon.juc.thread_basic;

import com.chandon.juc.SleepThread;

/**
 * 描述
 *
 * @author Dong
 * @version 1.0
 * @date 2021-04-07 13:38
 */

public class T04_Stop_Suspend_Thread {

    private static Object o = new Object();

    public static void main(String[] args) {
//        stopThreadTest();
//        suspendAndResume();

    }

    /**
     * 运行结果打印：
     *
     * in producer
     * producer is resume
     * in consumer
     * 程序无法结束
     * Dump Threads发现consumer是Runable状态
     * consuemr的resume先于suspend执行了，consumer永远的suspend了
     */
    static class MyThread {
        private static final Object lock = new Object();

        private static class Producer extends Thread {
            Producer() {
                super.setName("producer");
            }

            @Override
            public void run() {
                synchronized (lock) {
                    System.out.println("in producer");
                    Thread.currentThread().suspend();
                    System.out.println("producer is resume");
                }
            }
        }

        private static class Consumer extends Thread {
            Consumer() {
                super.setName("consumer");
            }

            @Override
            public void run() {
                synchronized (lock) {
                    System.out.println("in consumer");
                    Thread.currentThread().suspend();
                    System.out.println("consumer is resume");
                }
            }
        }

        static Producer producer = new Producer();
        static Consumer consumer = new Consumer();

        public static void main(String args[]) throws InterruptedException {
            // producer先拿到了锁，线程suspend
            producer.start();
            //防止producer的resume先于suspend执行
            Thread.sleep(2000);
            // consumer开始竞争锁
            consumer.start();
            // 唤醒producer,producer正常结束,consumer拿到锁开始执行
            producer.resume();
//            Thread.sleep(100);
            // consumer的resumer很有可能在还未拿到锁执行了，consumer就永远suspend在那里了
            // 控制台可以看到 main线程先于consumer执行完成了，自然就是resumer比suspend先执行了
            consumer.resume();
//            producer.join();
//            consumer.join();
            System.out.println("All shop");
        }
    }

    /**
     * suspend与resume不推荐使用原因是容易造成死锁
     * suspend必须在resume执行前，一旦resume先执行就会死锁
     * suspend不会释放锁，在某个线程在持有某个对非常重要的资源持有锁其它线程无法访问
     */
    private static void suspendAndResume() {
        Thread t = new Thread(() -> {

            synchronized (o) {
                System.out.println("执行开始");
                // 模拟逻辑执行耗时
                SleepThread.sleep(3);
                System.out.println("执行完毕");

            }
        });
        t.start();
        t.suspend();
        SleepThread.sleep(1);
        t.resume();
    }

    /**
     * stop停止线程过于暴力，且破坏synchronized的原子性
     */
    private static void stopThreadTest() {
        Thread t = new Thread(() -> {

            synchronized (o) {
                System.out.println("执行开始");
                // 模拟逻辑执行耗时
                SleepThread.sleep(3);
                System.out.println("执行完毕");

            }
        });
        t.start();
        SleepThread.sleep(1);
        t.stop();
    }

}
